package q1.project.web.jwt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Set;
import java.util.UUID;
import javax.crypto.SecretKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/** JWT Token 提供者 负责生成、解析、验证 JWT Token */
@Component
public class JwtTokenProvider {

  private static final Logger logger = LoggerFactory.getLogger(JwtTokenProvider.class);

  @Autowired private JwtProperties jwtProperties;

  /**
   * 生成双Token
   *
   * @param userId 用户ID
   * @param tenantId 租户ID
   * @param roles 角色集合
   * @param ip 客户端IP
   * @return JwtToken
   */
  public JwtToken generateToken(String userId, String tenantId, Set<String> roles, String ip) {
    String jti = UUID.randomUUID().toString();
    long now = System.currentTimeMillis();
    SecretKey key = Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes(StandardCharsets.UTF_8));

    String accessToken =
        Jwts.builder()
            .id(jti)
            .subject(userId)
            .claim("tenantId", tenantId)
            .claim("roles", roles)
            .claim("ip", ip)
            .claim("type", "access")
            .issuedAt(new Date(now))
            .expiration(new Date(now + jwtProperties.getAccessTokenExpiration()))
            .signWith(key, Jwts.SIG.HS512)
            .compact();

    String refreshToken =
        Jwts.builder()
            .id(jti)
            .subject(userId)
            .claim("type", "refresh")
            .issuedAt(new Date(now))
            .expiration(new Date(now + jwtProperties.getRefreshTokenExpiration()))
            .signWith(key, Jwts.SIG.HS512)
            .compact();

    return new JwtToken(
        accessToken, refreshToken, jwtProperties.getAccessTokenExpiration(), "Bearer", jti);
  }

  /**
   * 解析Token
   *
   * @param token JWT Token
   * @return Claims
   */
  public Claims parseToken(String token) {
    SecretKey key = Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes(StandardCharsets.UTF_8));
    return Jwts.parser()
        .verifyWith(key)
        .build()
        .parseSignedClaims(token)
        .getPayload();
  }

  /**
   * 验证Token
   *
   * @param token JWT Token
   * @param requestIp 请求IP
   * @return 是否有效
   */
  public boolean validateToken(String token, String requestIp) {
    try {
      Claims claims = parseToken(token);

      // 检查过期时间
      if (claims.getExpiration().before(new Date())) {
        return false;
      }

      // 检查IP绑定（可选）
      if (jwtProperties.getEnableIpBinding()) {
        String tokenIp = claims.get("ip", String.class);
        if (tokenIp != null && !tokenIp.equals(requestIp)) {
          logger.warn("Token IP不匹配: token={}, request={}", tokenIp, requestIp);
          return false;
        }
      }

      return true;
    } catch (Exception e) {
      logger.error("Token验证失败", e);
      return false;
    }
  }

  /**
   * 从Token中获取用户ID
   *
   * @param token JWT Token
   * @return 用户ID
   */
  public String getUserId(String token) {
    Claims claims = parseToken(token);
    return claims.getSubject();
  }

  /**
   * 从Token中获取租户ID
   *
   * @param token JWT Token
   * @return 租户ID
   */
  public String getTenantId(String token) {
    Claims claims = parseToken(token);
    return claims.get("tenantId", String.class);
  }

  /**
   * 从Token中获取JTI
   *
   * @param token JWT Token
   * @return JTI
   */
  public String getJti(String token) {
    Claims claims = parseToken(token);
    return claims.getId();
  }
}
